#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
int N, w, h;
struct cycle
{
	int x, y, r;
	//根据圆的右端点进行排序
	bool operator<(cycle a)
	{
		return x + r < a.x + a.r;
	}
}cy[1001]; //根据结构体数组存储全部的圆
int p[1001]; //存储每个圆的下端点
int solve(int ed)
{
	//创建优先队列（小根堆）存储圆的左端点
	priority_queue<int, vector<int>, greater<int>> q;
	int ans = 0;
	for (int i = 0; i < N; i++) //遍历全部圆
	{
		if (cy[i].y - cy[i].r<ed || cy[i].y + cy[i].r>ed + h) continue; //越界就continue
		int r = cy[i].x + cy[i].r;
		while (q.size() && r - q.top() > w) q.pop(); //因为要存储当前的圆，要将超过方框的圆删除
		int l = cy[i].x - cy[i].r;
		q.push(l); //将当前圆的左端点入队
		ans = max(ans, int(q.size())); //更新答案
	}
	return ans;
}
int main()
{
	//加速
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> N >> w >> h;
	for (int i = 0; i < N; i++)
	{
		cin >> cy[i].x >> cy[i].y >> cy[i].r;
		p[i] = cy[i].y - cy[i].r;
	}
	sort(cy, cy + N); //将所有圆的右端点按照升序排序
	sort(p, p + N); //将所有圆的下端点按照升序排序
	int ans = 0;
	//遍历所有圆的下端点为方框的下边界，方框的上下边界都确定了，调用solve函数就可以返回当前方框所框住最大圆的数量
	//再用ans记录方框所框住最大圆的数量
	for (int i = 0; i < N; i++) ans = max(ans, solve(p[i]));
	swap(w, h); //将方框90度翻转，也就是将w，h交换
	//再继续遍历所有圆的下端点为方框的下边界，更新ans的最大值
	for (int i = 0; i < N; i++) ans = max(ans, solve(p[i]));
	cout << ans; //返回答案
	return 0;
}